home *** CD-ROM | disk | FTP | other *** search
/ Freelog 100 / FreelogNo100-NovembreDecembre2010.iso / Musique / solfege / solfege-win32-3.17.0.exe / {app} / bin / Lib / bsddb / __init__.py next >
Text File  |  2007-12-10  |  14KB  |  402 lines

  1. #----------------------------------------------------------------------
  2. #  Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
  3. #  and Andrew Kuchling. All rights reserved.
  4. #
  5. #  Redistribution and use in source and binary forms, with or without
  6. #  modification, are permitted provided that the following conditions are
  7. #  met:
  8. #
  9. #    o Redistributions of source code must retain the above copyright
  10. #      notice, this list of conditions, and the disclaimer that follows.
  11. #
  12. #    o Redistributions in binary form must reproduce the above copyright
  13. #      notice, this list of conditions, and the following disclaimer in
  14. #      the documentation and/or other materials provided with the
  15. #      distribution.
  16. #
  17. #    o Neither the name of Digital Creations nor the names of its
  18. #      contributors may be used to endorse or promote products derived
  19. #      from this software without specific prior written permission.
  20. #
  21. #  THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
  22. #  IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  23. #  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  24. #  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL
  25. #  CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. #  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. #  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. #  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29. #  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  30. #  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  31. #  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  32. #  DAMAGE.
  33. #----------------------------------------------------------------------
  34.  
  35.  
  36. """Support for BerkeleyDB 3.3 through 4.4 with a simple interface.
  37.  
  38. For the full featured object oriented interface use the bsddb.db module
  39. instead.  It mirrors the Sleepycat BerkeleyDB C API.
  40. """
  41.  
  42. try:
  43.     if __name__ == 'bsddb3':
  44.         # import _pybsddb binary as it should be the more recent version from
  45.         # a standalone pybsddb addon package than the version included with
  46.         # python as bsddb._bsddb.
  47.         import _pybsddb
  48.         _bsddb = _pybsddb
  49.         from bsddb3.dbutils import DeadlockWrap as _DeadlockWrap
  50.     else:
  51.         import _bsddb
  52.         from bsddb.dbutils import DeadlockWrap as _DeadlockWrap
  53. except ImportError:
  54.     # Remove ourselves from sys.modules
  55.     import sys
  56.     del sys.modules[__name__]
  57.     raise
  58.  
  59. # bsddb3 calls it db, but provide _db for backwards compatibility
  60. db = _db = _bsddb
  61. __version__ = db.__version__
  62.  
  63. error = db.DBError  # So bsddb.error will mean something...
  64.  
  65. #----------------------------------------------------------------------
  66.  
  67. import sys, os
  68.  
  69. # for backwards compatibility with python versions older than 2.3, the
  70. # iterator interface is dynamically defined and added using a mixin
  71. # class.  old python can't tokenize it due to the yield keyword.
  72. if sys.version >= '2.3':
  73.     import UserDict
  74.     from weakref import ref
  75.     exec """
  76. class _iter_mixin(UserDict.DictMixin):
  77.     def _make_iter_cursor(self):
  78.         cur = _DeadlockWrap(self.db.cursor)
  79.         key = id(cur)
  80.         self._cursor_refs[key] = ref(cur, self._gen_cref_cleaner(key))
  81.         return cur
  82.  
  83.     def _gen_cref_cleaner(self, key):
  84.         # use generate the function for the weakref callback here
  85.         # to ensure that we do not hold a strict reference to cur
  86.         # in the callback.
  87.         return lambda ref: self._cursor_refs.pop(key, None)
  88.  
  89.     def __iter__(self):
  90.         try:
  91.             cur = self._make_iter_cursor()
  92.  
  93.             # FIXME-20031102-greg: race condition.  cursor could
  94.             # be closed by another thread before this call.
  95.  
  96.             # since we're only returning keys, we call the cursor
  97.             # methods with flags=0, dlen=0, dofs=0
  98.             key = _DeadlockWrap(cur.first, 0,0,0)[0]
  99.             yield key
  100.  
  101.             next = cur.next
  102.             while 1:
  103.                 try:
  104.                     key = _DeadlockWrap(next, 0,0,0)[0]
  105.                     yield key
  106.                 except _bsddb.DBCursorClosedError:
  107.                     cur = self._make_iter_cursor()
  108.                     # FIXME-20031101-greg: race condition.  cursor could
  109.                     # be closed by another thread before this call.
  110.                     _DeadlockWrap(cur.set, key,0,0,0)
  111.                     next = cur.next
  112.         except _bsddb.DBNotFoundError:
  113.             return
  114.         except _bsddb.DBCursorClosedError:
  115.             # the database was modified during iteration.  abort.
  116.             return
  117.  
  118.     def iteritems(self):
  119.         if not self.db:
  120.             return
  121.         try:
  122.             cur = self._make_iter_cursor()
  123.  
  124.             # FIXME-20031102-greg: race condition.  cursor could
  125.             # be closed by another thread before this call.
  126.  
  127.             kv = _DeadlockWrap(cur.first)
  128.             key = kv[0]
  129.             yield kv
  130.  
  131.             next = cur.next
  132.             while 1:
  133.                 try:
  134.                     kv = _DeadlockWrap(next)
  135.                     key = kv[0]
  136.                     yield kv
  137.                 except _bsddb.DBCursorClosedError:
  138.                     cur = self._make_iter_cursor()
  139.                     # FIXME-20031101-greg: race condition.  cursor could
  140.                     # be closed by another thread before this call.
  141.                     _DeadlockWrap(cur.set, key,0,0,0)
  142.                     next = cur.next
  143.         except _bsddb.DBNotFoundError:
  144.             return
  145.         except _bsddb.DBCursorClosedError:
  146.             # the database was modified during iteration.  abort.
  147.             return
  148. """
  149. else:
  150.     class _iter_mixin: pass
  151.  
  152.  
  153. class _DBWithCursor(_iter_mixin):
  154.     """
  155.     A simple wrapper around DB that makes it look like the bsddbobject in
  156.     the old module.  It uses a cursor as needed to provide DB traversal.
  157.     """
  158.     def __init__(self, db):
  159.         self.db = db
  160.         self.db.set_get_returns_none(0)
  161.  
  162.         # FIXME-20031101-greg: I believe there is still the potential
  163.         # for deadlocks in a multithreaded environment if someone
  164.         # attempts to use the any of the cursor interfaces in one
  165.         # thread while doing a put or delete in another thread.  The
  166.         # reason is that _checkCursor and _closeCursors are not atomic
  167.         # operations.  Doing our own locking around self.dbc,
  168.         # self.saved_dbc_key and self._cursor_refs could prevent this.
  169.         # TODO: A test case demonstrating the problem needs to be written.
  170.  
  171.         # self.dbc is a DBCursor object used to implement the
  172.         # first/next/previous/last/set_location methods.
  173.         self.dbc = None
  174.         self.saved_dbc_key = None
  175.  
  176.         # a collection of all DBCursor objects currently allocated
  177.         # by the _iter_mixin interface.
  178.         self._cursor_refs = {}
  179.  
  180.     def __del__(self):
  181.         self.close()
  182.  
  183.     def _checkCursor(self):
  184.         if self.dbc is None:
  185.             self.dbc = _DeadlockWrap(self.db.cursor)
  186.             if self.saved_dbc_key is not None:
  187.                 _DeadlockWrap(self.dbc.set, self.saved_dbc_key)
  188.                 self.saved_dbc_key = None
  189.  
  190.     # This method is needed for all non-cursor DB calls to avoid
  191.     # BerkeleyDB deadlocks (due to being opened with DB_INIT_LOCK
  192.     # and DB_THREAD to be thread safe) when intermixing database
  193.     # operations that use the cursor internally with those that don't.
  194.     def _closeCursors(self, save=1):
  195.         if self.dbc:
  196.             c = self.dbc
  197.             self.dbc = None
  198.             if save:
  199.                 try:
  200.                     self.saved_dbc_key = _DeadlockWrap(c.current, 0,0,0)[0]
  201.                 except db.DBError:
  202.                     pass
  203.             _DeadlockWrap(c.close)
  204.             del c
  205.         for cref in self._cursor_refs.values():
  206.             c = cref()
  207.             if c is not None:
  208.                 _DeadlockWrap(c.close)
  209.  
  210.     def _checkOpen(self):
  211.         if self.db is None:
  212.             raise error, "BSDDB object has already been closed"
  213.  
  214.     def isOpen(self):
  215.         return self.db is not None
  216.  
  217.     def __len__(self):
  218.         self._checkOpen()
  219.         return _DeadlockWrap(lambda: len(self.db))  # len(self.db)
  220.  
  221.     def __getitem__(self, key):
  222.         self._checkOpen()
  223.         return _DeadlockWrap(lambda: self.db[key])  # self.db[key]
  224.  
  225.     def __setitem__(self, key, value):
  226.         self._checkOpen()
  227.         self._closeCursors()
  228.         def wrapF():
  229.             self.db[key] = value
  230.         _DeadlockWrap(wrapF)  # self.db[key] = value
  231.  
  232.     def __delitem__(self, key):
  233.         self._checkOpen()
  234.         self._closeCursors()
  235.         def wrapF():
  236.             del self.db[key]
  237.         _DeadlockWrap(wrapF)  # del self.db[key]
  238.  
  239.     def close(self):
  240.         self._closeCursors(save=0)
  241.         if self.dbc is not None:
  242.             _DeadlockWrap(self.dbc.close)
  243.         v = 0
  244.         if self.db is not None:
  245.             v = _DeadlockWrap(self.db.close)
  246.         self.dbc = None
  247.         self.db = None
  248.         return v
  249.  
  250.     def keys(self):
  251.         self._checkOpen()
  252.         return _DeadlockWrap(self.db.keys)
  253.  
  254.     def has_key(self, key):
  255.         self._checkOpen()
  256.         return _DeadlockWrap(self.db.has_key, key)
  257.  
  258.     def set_location(self, key):
  259.         self._checkOpen()
  260.         self._checkCursor()
  261.         return _DeadlockWrap(self.dbc.set_range, key)
  262.  
  263.     def next(self):
  264.         self._checkOpen()
  265.         self._checkCursor()
  266.         rv = _DeadlockWrap(self.dbc.next)
  267.         return rv
  268.  
  269.     def previous(self):
  270.         self._checkOpen()
  271.         self._checkCursor()
  272.         rv = _DeadlockWrap(self.dbc.prev)
  273.         return rv
  274.  
  275.     def first(self):
  276.         self._checkOpen()
  277.         # fix 1725856: don't needlessly try to restore our cursor position
  278.         self.saved_dbc_key = None
  279.         self._checkCursor()
  280.         rv = _DeadlockWrap(self.dbc.first)
  281.         return rv
  282.  
  283.     def last(self):
  284.         self._checkOpen()
  285.         # fix 1725856: don't needlessly try to restore our cursor position
  286.         self.saved_dbc_key = None
  287.         self._checkCursor()
  288.         rv = _DeadlockWrap(self.dbc.last)
  289.         return rv
  290.  
  291.     def sync(self):
  292.         self._checkOpen()
  293.         return _DeadlockWrap(self.db.sync)
  294.  
  295.  
  296. #----------------------------------------------------------------------
  297. # Compatibility object factory functions
  298.  
  299. def hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None,
  300.             cachesize=None, lorder=None, hflags=0):
  301.  
  302.     flags = _checkflag(flag, file)
  303.     e = _openDBEnv(cachesize)
  304.     d = db.DB(e)
  305.     d.set_flags(hflags)
  306.     if pgsize is not None:    d.set_pagesize(pgsize)
  307.     if lorder is not None:    d.set_lorder(lorder)
  308.     if ffactor is not None:   d.set_h_ffactor(ffactor)
  309.     if nelem is not None:     d.set_h_nelem(nelem)
  310.     d.open(file, db.DB_HASH, flags, mode)
  311.     return _DBWithCursor(d)
  312.  
  313. #----------------------------------------------------------------------
  314.  
  315. def btopen(file, flag='c', mode=0666,
  316.             btflags=0, cachesize=None, maxkeypage=None, minkeypage=None,
  317.             pgsize=None, lorder=None):
  318.  
  319.     flags = _checkflag(flag, file)
  320.     e = _openDBEnv(cachesize)
  321.     d = db.DB(e)
  322.     if pgsize is not None: d.set_pagesize(pgsize)
  323.     if lorder is not None: d.set_lorder(lorder)
  324.     d.set_flags(btflags)
  325.     if minkeypage is not None: d.set_bt_minkey(minkeypage)
  326.     if maxkeypage is not None: d.set_bt_maxkey(maxkeypage)
  327.     d.open(file, db.DB_BTREE, flags, mode)
  328.     return _DBWithCursor(d)
  329.  
  330. #----------------------------------------------------------------------
  331.  
  332.  
  333. def rnopen(file, flag='c', mode=0666,
  334.             rnflags=0, cachesize=None, pgsize=None, lorder=None,
  335.             rlen=None, delim=None, source=None, pad=None):
  336.  
  337.     flags = _checkflag(flag, file)
  338.     e = _openDBEnv(cachesize)
  339.     d = db.DB(e)
  340.     if pgsize is not None: d.set_pagesize(pgsize)
  341.     if lorder is not None: d.set_lorder(lorder)
  342.     d.set_flags(rnflags)
  343.     if delim is not None: d.set_re_delim(delim)
  344.     if rlen is not None: d.set_re_len(rlen)
  345.     if source is not None: d.set_re_source(source)
  346.     if pad is not None: d.set_re_pad(pad)
  347.     d.open(file, db.DB_RECNO, flags, mode)
  348.     return _DBWithCursor(d)
  349.  
  350. #----------------------------------------------------------------------
  351.  
  352. def _openDBEnv(cachesize):
  353.     e = db.DBEnv()
  354.     if cachesize is not None:
  355.         if cachesize >= 20480:
  356.             e.set_cachesize(0, cachesize)
  357.         else:
  358.             raise error, "cachesize must be >= 20480"
  359.     e.set_lk_detect(db.DB_LOCK_DEFAULT)
  360.     e.open('.', db.DB_PRIVATE | db.DB_CREATE | db.DB_THREAD | db.DB_INIT_LOCK | db.DB_INIT_MPOOL)
  361.     return e
  362.  
  363. def _checkflag(flag, file):
  364.     if flag == 'r':
  365.         flags = db.DB_RDONLY
  366.     elif flag == 'rw':
  367.         flags = 0
  368.     elif flag == 'w':
  369.         flags =  db.DB_CREATE
  370.     elif flag == 'c':
  371.         flags =  db.DB_CREATE
  372.     elif flag == 'n':
  373.         flags = db.DB_CREATE
  374.         #flags = db.DB_CREATE | db.DB_TRUNCATE
  375.         # we used db.DB_TRUNCATE flag for this before but BerkeleyDB
  376.         # 4.2.52 changed to disallowed truncate with txn environments.
  377.         if file is not None and os.path.isfile(file):
  378.             os.unlink(file)
  379.     else:
  380.         raise error, "flags should be one of 'r', 'w', 'c' or 'n'"
  381.     return flags | db.DB_THREAD
  382.  
  383. #----------------------------------------------------------------------
  384.  
  385.  
  386. # This is a silly little hack that allows apps to continue to use the
  387. # DB_THREAD flag even on systems without threads without freaking out
  388. # BerkeleyDB.
  389. #
  390. # This assumes that if Python was built with thread support then
  391. # BerkeleyDB was too.
  392.  
  393. try:
  394.     import thread
  395.     del thread
  396.     if db.version() < (3, 3, 0):
  397.         db.DB_THREAD = 0
  398. except ImportError:
  399.     db.DB_THREAD = 0
  400.  
  401. #----------------------------------------------------------------------
  402.